#include <REGX52.H>  // 包含51单片机寄存器的头文件
#include <SEG.H>     // 数码管显示的头文件
#include <KEY.H>     // 按键处理的头文件
#include <Init.H>    // 系统初始化的头文件
#include <onewire.H> // 单总线通信协议的头文件，用于与DS18B20通信

void Delay1ms(unsigned int XMS); // 延时函数声明，用于产生1ms的延时

/* 全局变量定义 */
unsigned char Key_Slow_Down; // 按键防抖变量
unsigned char Key_Val, Key_Old, Key_Down, Key_Up; // 按键值变量
unsigned char SEG_Slow_Disp; // 数码管显示防抖变量
unsigned char SEG_Pos;       // 数码管显示位置变量
unsigned char SEG_dula_scan[8]={10,10,10,10,10,10,10,10}; // 数码管位选扫描变量
unsigned char SEG_Point_scan[8]={0,0,0,0,0,0,0,0}; // 数码管点选扫描变量
unsigned char SEG_Mode;      // 数码管显示模式变量

float Temperature;          // 存储温度值的变量

unsigned char T_Disp[2]={18,21}; // 显示的温度值变量
unsigned char T_Ctrol[2]={18,21}; // 温度控制值变量
unsigned char T_Index;               // 温度索引变量

bit T_EEP_Flag;                  // EEPROM标志位，用于判断是否从EEPROM读取温度值
bit T_Flag;                      // 温度显示标志位，用于交替显示两组温度值
unsigned int T_Delay500ms;       // 500ms延时计数变量

/* 按键处理函数 */
void Key_Porc()
{
    if(Key_Slow_Down)return;
    Key_Slow_Down=1;
    
    Key_Val=Key_KBD_Num(); // 读取按键值
    Key_Down=Key_Val&(Key_Old^Key_Val); // 检测按键按下
    Key_Up=~Key_Val&(Key_Old^Key_Val); // 检测按键释放
    Key_Old=Key_Val; // 更新按键值
    
    switch(Key_Down) // 根据按键值执行不同的操作
    {
        case 7 : // 模式切换按键
            if(++SEG_Mode==4)SEG_Mode=0; // 循环切换显示模式
        break;
        case 6 : // 温度值增加按键
            if(T_Index==0)
                if(++T_Disp[0]==99)T_Disp[0]=0; // 增加显示的温度值
            if(T_Index==1)
                if(++T_Disp[1]==99)T_Disp[1]=0;
        break;
        case 5 : // 温度值减少按键
            if(T_Index==0)
                if(--T_Disp[0]==0)T_Disp[0]=99; // 减少显示的温度值
            if(T_Index==1)
                if(--T_Disp[1]==0)T_Disp[1]=99;
        break;
        case 4 : // 温度索引切换按键
            if(SEG_Mode==1)
                T_Index^=1; // 切换温度索引
        break;  
    }
}

/* 数码管显示处理函数 */
void SEG_Porc()
{
    if(SEG_Slow_Disp)return;
    SEG_Slow_Disp=1;
    
    Temperature=rd_temperature(); // 读取温度值
    switch(SEG_Mode) // 根据显示模式显示不同的内容
    {
        case 0: // 显示实时温度
            // 设置数码管显示的值
            // ... 省略部分代码 ...
        break;
        case 1: // 显示设定温度
            // 设置数码管显示的值
            // ... 省略部分代码 ...
            if(T_EEP_Flag==1) // 如果EEPROM标志位为1，则从EEPROM读取温度值
            {
                T_Ctrol[0]=T_Disp[0]; // 将显示的温度值存储到控制变量中
                T_Ctrol[1]=T_Disp[1];
                T_Disp[0]= T_Ctrol[0]; // 将控制变量的值赋给显示变量
                T_Disp[1]= T_Ctrol[1];
                T_EEP_Flag=0; // 清除EEPROM标志位
            }
        break;
    }
}

/* 定时器0初始化函数 */
void Timer0Init(void) // 定时器0初始化，用于产生定时中断
{
    TMOD &= 0xF0; // 设置定时器模式
    TL0 = 0x18; // 设置定时器初值
    TH0 = 0xFC; // 设置定时器初值
    TF0 = 0; // 清除定时器溢出标志
    TR0 = 1; // 启动定时器0
    
    ET0=1; // 使能定时器0中断
    EA=1; // 开启全局中断
}

/* 定时器0中断服务函数 */
void Timer0_Server() interrupt 1 // 定时器0中断服务程序
{
    if(++Key_Slow_Down==15) // 按键防抖计数
        Key_Slow_Down=0;
    if(++SEG_Slow_Disp==500) // 数码管显示防抖计数
        SEG_Slow_Disp=0;
    if(++T_Delay500ms==500) // 500ms延时计数
    {
        T_Delay500ms=0;
        T_Flag^=1; // 切换温度显示标志位
    }
    
    if(++SEG_Pos==8) // 数码管位置计数
        SEG_Pos=0;
    LED_Disp(SEG_Pos,LED_Show[SEG_Pos]); // 根据位置和显示值控制LED显示
}

/* 延时函数 */
void Delay1ms(unsigned int XMS) // 延时1ms的函数
{
    unsigned char i, j;
    while(XMS--)
    {
        i = 11;
        j = 190;
        do
        {
            while (--j);
        } while (--i);
    }
}

/* 主函数 */
void main()
{
    Sys_Init(); // 系统初始化
    Timer0Init(); // 定时器初始化
    rd_temperature(); // 读取温度值
    Delay1ms(1000); // 延时1秒
    while(1) // 主循环
    {
        Key_Porc(); // 调用按键处理函数
        SEG_Porc(); // 调用数码管显示处理函数
    }
}